/*****************************************************************************
*
*  @file     CanDriver.c
*  @brief    CAN驱动
*
*  @author   丁祖雄
*  @email                                        
*  @version  V0.1
*  @date     2022/5/7
*  @license  /
*----------------------------------------------------------------------------*
*  Remark         : Description                                              *
*----------------------------------------------------------------------------*
*  Change History :                                                          *
*  <Date>     | <Version> | <Author>       | <Description>                   *
*----------------------------------------------------------------------------*
*  2022/5/7   | 0.1       | 丁祖雄         | 创建文件                        *
*----------------------------------------------------------------------------*
*
*****************************************************************************/

/***********************************************************************************************************************
**                                                    Includes                                                        **
***********************************************************************************************************************/
#include "CanDriver.h"
#include "Com.h"

/***********************************************************************************************************************
**                                           Global Variable Definitions                                              **
***********************************************************************************************************************/


/***********************************************************************************************************************
**                                            Private Macro Definitions                                               **
***********************************************************************************************************************/
#define CANDRIVER_CAN0_STB_PORT				GPIOA
#define CANDRIVER_CAN0_STB_PIN				GPIO_PIN_10
#define CANDRIVER_CAN0_RX_PORT				GPIOA
#define CANDRIVER_CAN0_RX_PIN				GPIO_PIN_11
#define CANDRIVER_CAN0_TX_PORT				GPIOA
#define CANDRIVER_CAN0_TX_PIN				GPIO_PIN_12

#define CANDRIVER_CAN1_STB_PORT				GPIOB
#define CANDRIVER_CAN1_STB_PIN				GPIO_PIN_14
#define CANDRIVER_CAN1_RX_PORT				GPIOB
#define CANDRIVER_CAN1_RX_PIN				GPIO_PIN_12
#define CANDRIVER_CAN1_TX_PORT				GPIOB
#define CANDRIVER_CAN1_TX_PIN				GPIO_PIN_13

/***********************************************************************************************************************
**                                            Private Type Definitions                                                **
***********************************************************************************************************************/


/***********************************************************************************************************************
**                                           Private Variable Definitions                                             **
***********************************************************************************************************************/
static can_receive_message_struct    CanDriver_CAN0_Rx0Msg;
static can_receive_message_struct    CanDriver_CAN1_Rx0Msg;


/***********************************************************************************************************************
**                                           Private Function Declarations                                            **
***********************************************************************************************************************/
static void CanDriver_GpioInit(void);
static void CanDriver_CanInit(void);

/***********************************************************************************************************************
**                                            Global Function Definitions                                             **
***********************************************************************************************************************/
/**
  * @brief  CAN初始化
  * @param  None
  * @retval None
  */
void CanDriver_Init(void)
{
    /* GPIO config */
    CanDriver_GpioInit();
	
    /* CAN config */
    CanDriver_CanInit();
}

/**
  * @brief  CAN发送报文
  * @param  canBus: CANDRIVER_BUS_ACAN, CANDRIVER_BUS_CHCAN
  *         canDlc: length of data, 0-8
  *         canDataPtr: point to data
  * @retval E_OK,E_NOT_OK
  */
Std_ReturnType CanDriver_Transmit(uint32 canBus, uint32 canId, uint8 canDlc, uint8 const* canDataPtr)
{
    can_trasnmit_message_struct CanDriver_TxMsg;
    uint32 can_periph;
    Std_ReturnType ret = E_OK;
    uint8 i;
    
    if ((NULL_PTR == canDataPtr) || (canDlc > 8u))
    {
        ret = E_NOT_OK;
    }
    else
    {
        /*clear variable*/
        can_struct_para_init(CAN_TX_MESSAGE_STRUCT, &CanDriver_TxMsg);

        CanDriver_TxMsg.tx_ft = CAN_FT_DATA;
        
        if ((0xF800000&canId)==0)//(CANDRIVER_BUS_ACAN == canBus)
        {
            /*standard frame*/
            CanDriver_TxMsg.tx_ff = CAN_FF_STANDARD;
            CanDriver_TxMsg.tx_sfid = canId;
					  //CanDriver_TxMsg.tx_efid = canId;
            can_periph = CAN0;
        }
        else if ((0xF800000&canId)!=0)//(CANDRIVER_BUS_CHCAN == canBus)
        {
            /*extended frame*/
            CanDriver_TxMsg.tx_ff = CAN_FF_EXTENDED;
            CanDriver_TxMsg.tx_efid = canId;
            can_periph = CAN0;
        }
        else
        {
            /*do not support CanBus*/
            ret = E_NOT_OK;
        }
        
        if (E_OK == ret)
        {
            /*set data length*/
            CanDriver_TxMsg.tx_dlen = canDlc;
            
            /*copy data*/
            for (i = 0; i < canDlc; i++)
            {
                CanDriver_TxMsg.tx_data[i] = canDataPtr[i];
            }
            
            /*transmit can message*/
            can_message_transmit(can_periph, &CanDriver_TxMsg);
        }
    }
    
    return ret;
}



/*
 * CAN0 interrupt handle
 */
void CAN0_TX_IRQHandler(void)
{
    Com_TxConfirmation(COM_CHANNEL_ACAN);
    /* clear interrupt flag */
    if (SET == can_interrupt_flag_get(CAN0, CAN_INT_FLAG_MTF0))
    {
        can_interrupt_flag_clear(CAN0, CAN_INT_FLAG_MTF0);
    }
    else if (SET == can_interrupt_flag_get(CAN0, CAN_INT_FLAG_MTF1))
    {
        can_interrupt_flag_clear(CAN0, CAN_INT_FLAG_MTF1);
    }
    else if (SET == can_interrupt_flag_get(CAN0, CAN_INT_FLAG_MTF2))
    {
        can_interrupt_flag_clear(CAN0, CAN_INT_FLAG_MTF2);
    }
    else
    {}
}

void CAN0_RX0_IRQHandler(void)
{
    /* check the receive message */
    can_message_receive(CAN0, CAN_FIFO0, &CanDriver_CAN0_Rx0Msg);
    
    /* notify upper layer */
	if(CanDriver_CAN0_Rx0Msg.rx_ff==CAN_FF_STANDARD)
	{
    Com_RxIndication(COM_CHANNEL_ACAN, CanDriver_CAN0_Rx0Msg.rx_sfid, CanDriver_CAN0_Rx0Msg.rx_ff,
        CanDriver_CAN0_Rx0Msg.rx_dlen, (const uint8*)(&(CanDriver_CAN0_Rx0Msg.rx_data)));
	}
	else if(CanDriver_CAN0_Rx0Msg.rx_ff==CAN_FF_EXTENDED)
	{
	  Com_RxIndication(COM_CHANNEL_ACAN, CanDriver_CAN0_Rx0Msg.rx_efid, CanDriver_CAN0_Rx0Msg.rx_ff,
       CanDriver_CAN0_Rx0Msg.rx_dlen, (const uint8*)(&(CanDriver_CAN0_Rx0Msg.rx_data)));
	}
		can_fifo_release(CAN0, CAN_FIFO0);
}

void CAN0_RX1_IRQHandler(void)
{
}

void CAN0_EWMC_IRQHandler(void)
{
    Com_BusOffIndication(COM_CHANNEL_ACAN);
    /* clear interrupt flag */
    can_interrupt_flag_clear(CAN0, CAN_INT_FLAG_ERRIF);
}


/*
 * CAN1 interrupt handle
 */
void CAN1_TX_IRQHandler(void)
{
    Com_TxConfirmation(COM_CHANNEL_CHCAN);
    /* clear interrupt flag */
    if (SET == can_interrupt_flag_get(CAN1, CAN_INT_FLAG_MTF0))
    {
        can_interrupt_flag_clear(CAN1, CAN_INT_FLAG_MTF0);
    }
    else if (SET == can_interrupt_flag_get(CAN1, CAN_INT_FLAG_MTF1))
    {
        can_interrupt_flag_clear(CAN1, CAN_INT_FLAG_MTF1);
    }
    else if (SET == can_interrupt_flag_get(CAN1, CAN_INT_FLAG_MTF2))
    {
        can_interrupt_flag_clear(CAN1, CAN_INT_FLAG_MTF2);
    }
    else
    {}
}

void CAN1_RX0_IRQHandler(void)
{
    /* check the receive message */
   // can_message_receive(CAN1, CAN_FIFO0, &CanDriver_CAN1_Rx0Msg);
    
    /* notify upper layer */
   // Com_RxIndication(COM_CHANNEL_CHCAN, CanDriver_CAN1_Rx0Msg.rx_efid,CanDriver_CAN1_Rx0Msg.rx_ff,
   //     CanDriver_CAN1_Rx0Msg.rx_dlen, (const uint8*)(&(CanDriver_CAN1_Rx0Msg.rx_data)));
}

void CAN1_RX1_IRQHandler(void)
{

}

void CAN1_EWMC_IRQHandler(void)
{
    Com_BusOffIndication(COM_CHANNEL_CHCAN);
    /* clear interrupt flag */
    can_interrupt_flag_clear(CAN1, CAN_INT_FLAG_ERRIF);
}

/***********************************************************************************************************************
**                                           Private Function Definitions                                             **
***********************************************************************************************************************/
static void CanDriver_GpioInit(void)
{
	/* enable CAN0 clock */
	rcu_periph_clock_enable(RCU_CAN0);
    rcu_periph_clock_enable(RCU_GPIOA);
    rcu_periph_clock_enable(RCU_AF);
    /* configure CAN0 GPIO */
    gpio_init(CANDRIVER_CAN0_RX_PORT, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, CANDRIVER_CAN0_RX_PIN);
    gpio_init(CANDRIVER_CAN0_TX_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, CANDRIVER_CAN0_TX_PIN);
    /* enable CAN0 transceiver*/
    gpio_init(CANDRIVER_CAN0_STB_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, CANDRIVER_CAN0_STB_PIN);
    gpio_bit_reset(CANDRIVER_CAN0_STB_PORT, CANDRIVER_CAN0_STB_PIN);
	
	/* enable CAN1 clock */
	rcu_periph_clock_enable(RCU_CAN1);
    rcu_periph_clock_enable(RCU_GPIOB);
    rcu_periph_clock_enable(RCU_AF);
    /* configure CAN1 GPIO */
    gpio_init(CANDRIVER_CAN1_RX_PORT, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, CANDRIVER_CAN1_RX_PIN);
    gpio_init(CANDRIVER_CAN1_TX_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, CANDRIVER_CAN1_TX_PIN);
    /* enable CAN1 transceiver*/
    gpio_init(CANDRIVER_CAN1_STB_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, CANDRIVER_CAN1_STB_PIN);
    gpio_bit_reset(CANDRIVER_CAN1_STB_PORT, CANDRIVER_CAN1_STB_PIN);
}

static void CanDriver_CanInit(void)
{
    can_parameter_struct          can_parameter;
	  can_filter_parameter_struct   can_filter_parameter;

    /*
     * CAN0-ACAN
     */
    can_struct_para_init(CAN_INIT_STRUCT, &can_parameter);
	  can_struct_para_init(CAN_FILTER_STRUCT, &can_filter_parameter);
    /* initialize CAN register */
    can_deinit(CAN0);

    /* initialize CAN */
    can_parameter.time_triggered         = DISABLE;
    can_parameter.auto_bus_off_recovery  = ENABLE;
    can_parameter.auto_wake_up           = DISABLE;
    can_parameter.no_auto_retrans        = DISABLE;
    can_parameter.rec_fifo_overwrite     = DISABLE;
    can_parameter.trans_fifo_order       = ENABLE;
    can_parameter.working_mode           = CAN_NORMAL_MODE;
    can_parameter.resync_jump_width      = CAN_BT_SJW_1TQ;
    can_parameter.time_segment_1         = CAN_BT_BS1_5TQ;
    can_parameter.time_segment_2         = CAN_BT_BS2_4TQ;
    can_parameter.prescaler              = 24;     //波特率配置为250k,配置为500k，对应系数为12
    can_init(CAN0, &can_parameter);
    
    /* initialize filter */ 
    can_filter_parameter.filter_number        = 0;
    can_filter_parameter.filter_mode          = CAN_FILTERMODE_MASK;
    can_filter_parameter.filter_bits          = CAN_FILTERBITS_32BIT;
    can_filter_parameter.filter_list_high     = 0x0000;
    can_filter_parameter.filter_list_low      = 0x0000;
    can_filter_parameter.filter_mask_high     = 0x0000;
    can_filter_parameter.filter_mask_low      = 0x0000;
    can_filter_parameter.filter_fifo_number   = CAN_FIFO0;
    can_filter_parameter.filter_enable        = ENABLE;
    can_filter_init(&can_filter_parameter);

	/*receive FIFO0 not empty interrupt enable*/
	nvic_irq_enable(CAN0_RX0_IRQn,0,0);
	can_interrupt_enable(CAN0, CAN_INT_RFNE0);
    /*bus-off interrupt enable*/
    nvic_irq_enable(CAN0_EWMC_IRQn,0,0);
    can_interrupt_enable(CAN0, CAN_INT_ERR);
    can_interrupt_enable(CAN0, CAN_INT_BO);
    /*transmit mailbox empty interrupt enable*/
    nvic_irq_enable(CAN0_TX_IRQn,0,0);
	can_interrupt_enable(CAN0, CAN_INT_TME);
    
    
    /*
     * CAN1-CHCAN
     */
    can_struct_para_init(CAN_INIT_STRUCT, &can_parameter);
	  can_struct_para_init(CAN_FILTER_STRUCT, &can_filter_parameter);
    /* initialize CAN register */
    can_deinit(CAN1);

    /* initialize CAN */
    can_parameter.time_triggered         = DISABLE;
    can_parameter.auto_bus_off_recovery  = ENABLE;
    can_parameter.auto_wake_up           = DISABLE;
    can_parameter.no_auto_retrans        = DISABLE;
    can_parameter.rec_fifo_overwrite     = DISABLE;
    can_parameter.trans_fifo_order       = ENABLE;
    can_parameter.working_mode           = CAN_NORMAL_MODE;
    can_parameter.resync_jump_width      = CAN_BT_SJW_1TQ;
    can_parameter.time_segment_1         = CAN_BT_BS1_5TQ;
    can_parameter.time_segment_2         = CAN_BT_BS2_4TQ;
    can_parameter.prescaler              = 24;
    can_init(CAN1, &can_parameter);
    
    /* initialize filter */ 
    can_filter_parameter.filter_number        = 15;
    can_filter_parameter.filter_mode          = CAN_FILTERMODE_MASK;
    can_filter_parameter.filter_bits          = CAN_FILTERBITS_32BIT;
    can_filter_parameter.filter_list_high     = 0x0000;
    can_filter_parameter.filter_list_low      = 0x0000;
    can_filter_parameter.filter_mask_high     = 0x0000;
    can_filter_parameter.filter_mask_low      = 0x0000;
    can_filter_parameter.filter_fifo_number   = CAN_FIFO0;
    can_filter_parameter.filter_enable        = ENABLE;
    can_filter_init(&can_filter_parameter);

	/*receive FIFO0 not empty interrupt enable*/
	nvic_irq_enable(CAN1_RX0_IRQn,0,0);
	can_interrupt_enable(CAN1, CAN_INT_RFNE0);
    /*bus-off interrupt enable*/
    nvic_irq_enable(CAN1_EWMC_IRQn,0,0);
    can_interrupt_enable(CAN1, CAN_INT_ERR);
    can_interrupt_enable(CAN1, CAN_INT_BO);
    /*transmit mailbox empty interrupt enable*/
    nvic_irq_enable(CAN1_TX_IRQn,0,0);
	can_interrupt_enable(CAN1, CAN_INT_TME);
}


/***********************************************************************************************************************
**                                                  General Notes                                                     **
***********************************************************************************************************************/

